package com.clx.admin.controller;


import com.clx.admin.service.FileService;
import com.clx.common.controller.BaseController;
import com.clx.common.domain.dto.FileUploadChunkDto;
import com.clx.common.domain.entity.DiskFile;
import com.clx.common.domain.vo.AjaxResult;
import com.clx.common.domain.vo.TableDataInfo;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.errors.*;
import io.minio.http.Method;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 文件表(File)表控制层
 *
 * @author clx
 * @since 2025-01-10 11:48:23
 */
@RestController
@RequestMapping("file")
@RequiredArgsConstructor
@Slf4j
public class FileController extends BaseController {
    /**
     * 依赖注入
     */
    private final FileService fileService;


    @Value("${minio.bucketName}")
    private String bucketName;


    private final MinioClient minioClient;



    /**
     * 查询列表
     */

    @GetMapping("/list")
    public TableDataInfo list(DiskFile file) {
//        startPage();
        List<DiskFile> list = fileService.selectFileList(file);
        return getDataTable(list);
    }

    /**
     * 获取详细信息
     */
    @GetMapping("/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return success(fileService.selectFileById(id));
    }

    /**
     * 新增数据
     */
    @PostMapping
    public AjaxResult add(@RequestBody DiskFile file) {
        return toAjax(fileService.insertFile(file));
    }

    /**
     * 修改数据
     */
    @PutMapping
    public AjaxResult edit(@RequestBody DiskFile file) {
        return toAjax(fileService.updateFile(file));
    }

    /**
     * 删除数据
     */
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(fileService.deleteFileByIds(ids));
    }

    /**
     * 分页查询
     */
    @GetMapping("/paging")
    public TableDataInfo paging(@RequestParam("pageNum") int pageNum,@RequestParam("pageSize") int pageSize,@RequestParam("index") int index){
        List<DiskFile> paging = fileService.paging(pageNum, pageSize,index);
        return getDataTable(paging);
    }

    /**
     * 文件小于5mb直接上传
     */
    @PostMapping("/uploadSmall")
    public AjaxResult uploadSmall( FileUploadChunkDto fileUploadChunkDto) {
        return fileService.uploadSmall(fileUploadChunkDto);
    }



    /**
     * 上传分块文件
     *
     */
    @PostMapping("/upload")
    public AjaxResult upload( FileUploadChunkDto fileUploadChunkDto) {
       // TODO 判断是否登录,或者全局拦截器
        return fileService.upload(fileUploadChunkDto);
    }

    /**
     * 合并分片
     */
    @PostMapping("/merge")
    public AjaxResult merge( FileUploadChunkDto fileUploadChunkDto){
        return fileService.merge(fileUploadChunkDto);
    }


    /**
     * 根据用户id查询文件
     */
    @GetMapping("/userFile")
    public AjaxResult selectFile(){
        return fileService.selectFile();
    }


    /**
     * 返回文件类型对应的list
     */
    @GetMapping("/type/{index}")
    public AjaxResult selectByType(@PathVariable Long index){
        return fileService.selectByType(index);
    }

    /**
     * 文件搜索功能
     */
    @GetMapping("/search")
    public TableDataInfo searchByFile(@RequestParam("value") String value,@RequestParam("pageNum") int pageNum,@RequestParam("pageSize") int pageSize){
        List<DiskFile> diskFiles = fileService.searchByFile(value, pageNum, pageSize);
        return getDataTable(diskFiles);
    }

    /**
     * 获取文件的预览地址
     * @param file
     * @return
     */
    @PostMapping("/preview")
    public AjaxResult previewFile(@RequestBody DiskFile file) {
        String objectName = file.getFileName();
        try {
            // 1. 创建要传递的查询参数（关键修改）
            Map<String, String> queryParams = new HashMap<>();
            queryParams.put("response-content-type", getContentType(objectName));
            queryParams.put("response-content-disposition", "inline; filename=\"" + objectName + "\"");

            String presignedObjectUrl = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                    .bucket(bucketName)
                    .method(Method.GET)
                    .object(file.getFilePath())
                    .expiry(30, TimeUnit.MINUTES)
                    .extraQueryParams(queryParams)
                    .build());
            return AjaxResult.success(null,presignedObjectUrl); // 返回 URL 作为数据
        } catch (Exception e) {
            return AjaxResult.error("获取预览地址失败");
        }
    }
    // 3. 完整的Content-Type判断方法
    private String getContentType(String filename) {
        String extension = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
        switch (extension) {
            case "mp4": return "video/mp4";
            case "mkv": return "video/x-matroska";
            case "pdf": return "application/pdf";
            case "jpg":
            case "jpeg": return "image/jpeg";
            case "png": return "image/png";
            case "doc": return "application/msword";
            case "docx": return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
            default: return "application/octet-stream";
        }
    }


    /**
     * 合并文件夹分块
     * @return
     */
    @PostMapping("/mergeFolder")
    public AjaxResult mergeChunks(FileUploadChunkDto fileUploadChunkDto) {
        return fileService.mergeChunks(fileUploadChunkDto);
    }



    /**
     * 根据文件的相对路径，把文件夹创建
     * @param  params
     * @return
     */
    @PostMapping("/ensureDirectory")
    public AjaxResult getFolderName(@RequestBody Map<String, String> params)
    {
        return fileService.getFolderName(params);
    }




    /**
     * 通过文件夹名称获取文件内容
     * @param folderName
     * @param filePath
     * @return
     */
    @GetMapping("/listObjects")
    public TableDataInfo listObjects(@RequestParam("filePath") String filePath,
                                  @RequestParam("folderName") String folderName,
                                  @RequestParam("pageNum") int pageNum,
                                  @RequestParam("pageSize") int pageSize)  {

        return getDataTable(fileService.listObjects(filePath,folderName,pageNum,pageSize));
    }


    /**
     * 根据id返回上一级
     * @param id
     * @return
     */
    @GetMapping("/returnToParent")
    public AjaxResult returnToParent(@RequestParam("id") Long id)  {

        return fileService.returnToParent(id);
    }


    /**
     * 彻底删除文件以及文件夹
     * @param
     * @return
     */
    @PostMapping("/delete")
    public AjaxResult move(@RequestBody List<DiskFile> fileList){
        return fileService.move(fileList);
    }

    /**
     *删除文件以及文件夹到回收站(修改状态)
     * @param
     * @return
     */
    @PostMapping("/update")
    public AjaxResult update(@RequestBody List<DiskFile> fileList){
        return fileService.update(fileList);
    }


    /**
     * 下载文件
     * @param
     * @return
     */
    @PostMapping ("/download")
    public void downLoadFile(@RequestBody List<DiskFile> list,HttpServletResponse response){
        fileService.downLoad(list,response);
    }


    /**
     * 新建文件夹
     * @param
     * @return
     */
    @GetMapping("/createFolder")
    public AjaxResult newFolder(@RequestParam("folderName") String folderName,@RequestParam(value = "parentId",required = false) Long parentId ){//允许parentId为空
        return fileService.newFolder(folderName,parentId);
    }


    /**
     * 恢复回收站文件
     * @param
     * @return
     */
    @PutMapping("/recover")
    public AjaxResult recover(@RequestBody List<DiskFile> fileList){
        return fileService.recover(fileList);
    }


    /**
     * 重命名
     * @param
     * @return
     */
    @PutMapping("/rename")
    public AjaxResult rename(@RequestBody DiskFile file){
        return fileService.rename(file);
    }

    // 获取文件后缀名
    private String getFileExtension(String name) {
        int lastIndex = name.lastIndexOf('.');
        if (lastIndex == -1) {
            return "";
        }
        return name.substring(lastIndex + 1);
    }

    // 根据文件后缀名设置 Content-Type 的方法
    private void setContentType(HttpServletResponse response, String fileExtension) {
        if (fileExtension.equalsIgnoreCase("mp4")) {
            response.setContentType("video/mp4");
        } else if (fileExtension.equalsIgnoreCase("pdf")) {
            response.setContentType("application/pdf");
        } else if (fileExtension.equalsIgnoreCase("jpg") || fileExtension.equalsIgnoreCase("jpeg") || fileExtension.equalsIgnoreCase("png")) {
            response.setContentType("image/jpeg");
        } else if (fileExtension.equalsIgnoreCase("doc") || fileExtension.equalsIgnoreCase("docx")) {
            response.setContentType("application/msword");
        } else {
            response.setContentType("application/octet-stream");
        }
    }

}